%% --- main function.
function varargout = CAN_S9132(varargin)
% CAN_S9132 MATLAB code for CAN_S9132.fig
%      CAN_S9132, by itself, creates a new CAN_S9132 or raises the existing
%      singleton*.
%
%      H = CAN_S9132 returns the handle to a new CAN_S9132 or the handle to
%      the existing singleton*.
%
%      CAN_S9132('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in CAN_S9132.M with the given input arguments.
%
%      CAN_S9132('Property','Value',...) creates a new CAN_S9132 or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before CAN_S9132_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to CAN_S9132_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help CAN_S9132

% Last Modified by GUIDE v2.5 23-Aug-2023 17:15:46

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @CAN_S9132_OpeningFcn, ...
                   'gui_OutputFcn',  @CAN_S9132_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

%% --- Executes just before CAN_S9132 is made visible.
function CAN_S9132_OpeningFcn(hObject, eventdata, handles, varargin)
% 设备初始化
global CONNECTED DEVICETYPE DEVICEINDEX CANINDEX can_signal can_signal_str can_signal_stdid can_signal_rxdata FRAME SENDNUMS;
global SunCoorX SunCoorY SunAngleX SunAngleY saveline FramesCell time_cell rtc_time StoreFileName CanOpened hexPath redata im_ty;

% 初始化变量
CONNECTED = 0; 
DEVICETYPE = 4;
DEVICEINDEX = 0;
CANINDEX = 0;
can_signal_str = '默认指令';
can_signal_stdid = '01000';
can_signal_rxdata = strcat('0000','0000','0000','0000');
SunCoorX = 0;
SunCoorY = 0;
SunAngleX = 0;
SunAngleY = 0;
saveline = 0;
FramesCell = {};
time_cell = {};
CanOpened = 0;

% 加载显示天银图标
im_ty = imread('ty-space.jpg');
axes(handles.axes1);
imshow(im_ty);

% 显示图像初始化
imagex = zeros(1,256);
imagey = zeros(1,256);
axes(handles.axes2);
plot_S9132_Source_Image(imagex, imagey);
axes(handles.axes3);
plot_S9132_Process_Image(imagex, imagey);
axes(handles.axes4);
plot_S9132_OutputData(imagex);
title("x轴数据曲线");
axes(handles.axes5);
plot_S9132_OutputData(imagey);
title("y轴数据曲线");

% 初始化 CAN 信号结构体
can_signal = init_CAN();
set(handles.edit_CAN_StdID,'String', can_signal_stdid);
set(handles.edit_CAN_rxdata,'String', can_signal_rxdata);

% 更新handles结构
handles.output = hObject;
guidata(hObject, handles);

% 设备初始化
global CONNECTED; % 开始时，设置为断开
CONNECTED = 0; 
global DEVICETYPE; % 设备类型，使用can时设置为4，修改后会报错
DEVICETYPE=4;
global DEVICEINDEX; % 设备索引
DEVICEINDEX=0;
global CANINDEX; % CAN索引
CANINDEX=0;

% 初始化太阳位置坐标
global SunCoorX; 
SunCoorX = 0;
global SunCoorY;
SunCoorX = 0;

% 初始化太阳角度
global SunAngleX; 
SunAngleX = 0;
global SunAngleY;
SunAngleX = 0;

% 存储变量
global saveline;
saveline = 0;
global FramesCell;
FramesCell = {};
global time_cell;
time_cell = {};


%% --- Outputs from this function are returned to the command line.
function varargout = CAN_S9132_OutputFcn(hObject, eventdata, handles) 
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;


%% can 函数：初始化 CAN 设备
function [status, msg] = init_CAN_device(deviceType, deviceIndex, canIndex)
% 初始化CAN设备
% 输入参数：
%   deviceType - 设备类型
%   deviceIndex - 设备索引
%   canIndex - CAN索引
% 输出参数：
%   status - 状态码(0:成功, 1:失败)
%   msg - 状态信息

% 打开设备
if ~VCI_OpenDevice(deviceType, deviceIndex, canIndex)
    status = 1;
    msg = '打开CAN设备失败';
    return;
end

% 初始化CAN
initConfig = [0 4294967295 0 1 0 28 0]; % [AccCode AccMask Reserved Filter Timing0 Timing1 Mode]
if VCI_InitCAN(deviceType, deviceIndex, canIndex, initConfig) ~= 1
    status = 1;
    msg = '初始化CAN失败';
    return;
end

% 启动CAN
if VCI_StartCAN(deviceType, deviceIndex, canIndex) ~= 1
    status = 1;
    msg = '启动CAN失败';
    return;
end

status = 0;
msg = 'CAN设备初始化成功';

%% can 函数：发送 CAN 帧
function [status, msg] = send_CAN_frame(deviceType, deviceIndex, canIndex, frame, sendNums)
% 发送CAN帧
% 输入参数：
%   deviceType - 设备类型
%   deviceIndex - 设备索引
%   canIndex - CAN索引
%   frame - CAN帧数据
%   sendNums - 发送次数
% 输出参数：
%   status - 状态码(0:成功, 1:失败)
%   msg - 状态信息

% 发送数据
success = VCI_Transmit(deviceType, deviceIndex, canIndex, frame, sendNums);
if success ~= sendNums
    status = 1;
    msg = sprintf('发送失败，期望发送%d帧，实际发送%d帧', sendNums, success);
    return;
end

status = 0;
msg = '发送成功';

%% can 函数：接收 CAN 帧
function [status, msg, frames] = receive_CAN_frame(deviceType, deviceIndex, canIndex, maxFrames, timeout)
% 接收CAN帧
% 输入参数：
%   deviceType - 设备类型
%   deviceIndex - 设备索引
%   canIndex - CAN索引
%   maxFrames - 最大接收帧数
%   timeout - 超时时间(ms)
% 输出参数：
%   status - 状态码(0:成功, 1:失败)
%   msg - 状态信息
%   frames - 接收到的帧数据

% 接收数据
[getLength, frames] = VCI_Receive(deviceType, deviceIndex, canIndex, maxFrames, timeout);
if getLength == 0
    status = 1;
    msg = '接收超时';
    return;
end

status = 0;
msg = sprintf('成功接收%d帧数据', getLength);

%% can 函数：关闭 CAN 设备
function [status, msg] = close_CAN_device(deviceType, deviceIndex)
% 关闭CAN设备
% 输入参数：
%   deviceType - 设备类型
%   deviceIndex - 设备索引
% 输出参数：
%   status - 状态码(0:成功, 1:失败)
%   msg - 状态信息

if VCI_CloseDevice(deviceType, deviceIndex) ~= 1
    status = 1;
    msg = '关闭CAN设备失败';
    return;
end

status = 0;
msg = '关闭CAN设备成功';

%% can 函数：连接 can 芯片
function pushbutton_connect_can_Callback(hObject, eventdata, handles)
global CONNECTED DEVICETYPE DEVICEINDEX CANINDEX;

if CONNECTED ~= 1
    [status, msg] = init_CAN_device(DEVICETYPE, DEVICEINDEX, CANINDEX);
    if status == 0
        CONNECTED = 1;
        set(hObject,'String','断开CAN');
        disp(msg);
    else
        disp(msg);
    end
else
    [status, msg] = close_CAN_device(DEVICETYPE, DEVICEINDEX);
    if status == 0
        CONNECTED = 0;
        set(hObject,'String','连接CAN');
        reset_panel(handles);
        disp(msg);
    else
        disp(msg);
    end
end

%% can 函数：返回设备信息
% --- Executes on button press in pushbutton_DeviceInfo.
function pushbutton_DeviceInfo_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_DeviceInfo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global CONNECTED DEVICETYPE DEVICEINDEX;

if CONNECTED == 1
    [result, info] = VCI_ReadBoardInfo(DEVICETYPE, DEVICEINDEX);
    str0 = sprintf('硬件版本号:%x\n固件版本号:%x\n驱动程序版本号:%x\n接口库版本号:%x\n板卡所使用的中断号:%x\nCAN通道:%x\n', ...
        info{1}, info{2}, info{3}, info{4}, info{5}, info{6});
    str = strcat(str0, '     序列号:', info{7}, '     硬件类型:', info{8}, '     系统保留', info{9});
    disp(str);
else
    disp("CAN 未连接");
end


%% can 函数：重启 can
% --- Executes on button press in pushbutton_ResetCan.
function pushbutton_ResetCan_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_ResetCan (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global DEVICETYPE DEVICEINDEX CANINDEX;

if VCI_ResetCAN(DEVICETYPE, DEVICEINDEX, CANINDEX) ~= 1
    disp('复位 CAN 失败！');
else
    disp('复位 CAN 成功！');
end


%% can 函数：发送命令，获取返回数据
function [GetLength, Frames] = Can_Communication(FRAME, SENDNUMS, LEN)
global DEVICETYPE DEVICEINDEX CANINDEX can_signal_str;

disp('开始发送CAN指令...');
disp(['指令类型: ', can_signal_str]);
disp(['发送帧数: ', num2str(SENDNUMS)]);
disp(['期望接收长度: ', num2str(LEN)]);

% 显示仲裁域和数据域内容
disp('发送指令内容:');
disp(['仲裁域(ID): ', num2str(FRAME(1))]);
disp(['时间戳: ', num2str(FRAME(2))]);
disp(['时间标志: ', num2str(FRAME(3))]);
disp(['发送类型: ', num2str(FRAME(4))]);
disp(['远程标志: ', num2str(FRAME(5))]);
disp(['扩展标志: ', num2str(FRAME(6))]);
disp(['数据长度: ', num2str(FRAME(7))]);
disp('数据域:');
for i = 1:FRAME(7)
    disp(['字节', num2str(i), ': ', num2str(FRAME(7+i))]);
end

% 发送数据
[status, msg] = send_CAN_frame(DEVICETYPE, DEVICEINDEX, CANINDEX, FRAME, SENDNUMS);
if status ~= 0
    disp(msg);
    GetLength = 0;
    Frames = [];
    return;
end

% 接收数据
[status, msg, Frames] = receive_CAN_frame(DEVICETYPE, DEVICEINDEX, CANINDEX, LEN, 100);
if status ~= 0
    disp(msg);
    GetLength = 0;
    return;
end

GetLength = size(Frames, 1);
disp(['实际接收长度: ', num2str(GetLength), ' 帧']);

%% 面板函数：选择指令
% --- Executes on selection change in popupmenu_CAN.
function popupmenu_CAN_Callback(hObject, eventdata, handles)
% hObject    handle to popupmenu_CAN (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns popupmenu_CAN contents as cell array
%        contents{get(hObject,'Value')} returns selected item from popupmenu_CAN

% 选择指令
global can_signal_str;
global can_signal_stdid;
global can_signal_rxdata;

contents = cellstr(get(hObject,'String'));
can_signal_str = contents{get(hObject,'Value')};
select_can_signal(handles);

function select_can_signal(handles)
% handles    structure with handles and user data (see GUIDATA)

global can_signal_str;
global can_signal_stdid;
global can_signal_rxdata;
% 设置相应的指令
switch can_signal_str
    case '默认指令'
        can_signal_rxdata = strcat('0000','0000','0000','0000');
    case '传图'
        can_signal_rxdata = strcat('0A2B','0001','0000','0000');
    case '实验'
        can_signal_rxdata = strcat('0A2B','0101','0000','0000');
    case '遥测'
        can_signal_rxdata = strcat('0AFF','FF00','0000','0000');
    case '修改ID'
        % 取设备ID值, 设置指令
        gu8_CAN_ID = get(handles.edit_Equipment_ID, 'String');
        gu8_CAN_ID_dec = bin2dec(gu8_CAN_ID);
        gu8_CAN_ID_str = pad(dec2hex(gu8_CAN_ID_dec),2,'left','0');
        can_signal_rxdata = strcat('0A1B','00',gu8_CAN_ID_str,'0000','0000');
        set(handles.edit_CAN_rxdata,'String',can_signal_rxdata);
        disp(can_signal_stdid);
        disp(can_signal_rxdata);
    case '修改图形固定阈值'
        % 取图形固定阈值, 设置指令
        image_threshold = get(handles.edit_can_image_threshold, 'String');
        image_threshold_num = str2num(image_threshold);
        image_threshold_str = pad(dec2hex(image_threshold_num),2,'left','0');
        can_signal_rxdata = strcat('0A1B','01',image_threshold_str,'0000','0000');
        set(handles.edit_CAN_rxdata,'String',can_signal_rxdata);
        disp(can_signal_rxdata);
    case '修改太阳能量固定阈值'
        % 取太阳能量固定阈值, 设置指令
        sun_threshold = get(handles.edit_sun_energy_threshold, 'String');
        % 将数据转变为高位在前
        sun_threshold_num = str2num(sun_threshold);
        sun_threshold_bin = dec2bin(sun_threshold_num);
        sun_threshold_bin = strcat(repmat('0',1,(32-length(sun_threshold_bin))), sun_threshold_bin);
        sun_threshold_str = '';
        for i=1:4
            temp = dec2hex(bin2dec(sun_threshold_bin((i-1)*8+1:i*8)));
            temp = strcat(repmat('0',1,(2-length(temp))), temp);
            sun_threshold_str = strcat(sun_threshold_str,temp);
        end
        can_signal_rxdata = strcat('0A1B','02',sun_threshold_str, '00');
        set(handles.edit_CAN_rxdata,'String',can_signal_rxdata);
        disp(can_signal_rxdata);
    case '修改跟踪阈值'
        % 取跟踪阈值, 设置指令
        track_threshold = get(handles.edit_can_track_threshold, 'String');
        % 将数据转变为高位在前
        track_threshold_num = str2num(track_threshold);
        track_threshold_bin = dec2bin(track_threshold_num);
        track_threshold_bin = strcat(repmat('0',1,(16-length(track_threshold_bin))), track_threshold_bin);
        track_threshold_str = '';
        for i=1:2
            temp = dec2hex(bin2dec(track_threshold_bin((i-1)*8+1:i*8)));
            temp = strcat(repmat('0',1,(2-length(temp))), temp);
            track_threshold_str = strcat(track_threshold_str,temp);
        end
        can_signal_rxdata = strcat('0A1B','03',track_threshold_str,'00','0000');
        set(handles.edit_CAN_rxdata,'String',can_signal_rxdata);
        disp(can_signal_rxdata);
    case '系统复位'
        can_signal_rxdata = strcat('0A1B','0400','0000','0000');
    otherwise
        can_signal_rxdata = strcat('00FF','0000','00FF','0000');
end
set(handles.edit_CAN_StdID,'String', can_signal_stdid);
set(handles.edit_CAN_rxdata,'String',can_signal_rxdata);


%% 面板函数：创建指令弹出式菜单
% --- Executes during object creation, after setting all properties.
function popupmenu_CAN_CreateFcn(hObject, eventdata, handles)
% hObject    handle to popupmenu_CAN (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

%% 遥测函数：发送单次指令
% --- Executes on button press in pushbutton_SendCanSignal.
function pushbutton_SendCanSignal_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_SendCanSignal (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% 全局变量定义
global DEVICETYPE;
global DEVICEINDEX;
global CANINDEX;
global val;
global sendcnt;
global recvcnt;
global can_signal;
global can_signal_str;
global can_signal_stdid;
global can_signal_rxdata;
global FRAME;
global SENDNUMS;
global SunCoorX;
global SunCoorY;
global SunAngleX;
global SunAngleY;
global StoreFileName;

sendcnt=0;
recvcnt=0;

% 读取一遍选择的命令
select_can_signal(handles);

% 设置 CAN 指令
can_signal = init_CAN();
can_signal('ID') = bin2dec(strcat('000',can_signal_stdid,'000'));
can_signal = set_CAN_Data(can_signal, can_signal_rxdata);
FRAME = gen_CAN_Frame(can_signal);
SENDNUMS = can_signal('SendNums');

% 创建存储文件名称
currentTime = datetime('now'); 
currentTime_str = datestr(currentTime,'yyyy_mm_dd_HH_MM_SS');
StoreFileName = strcat(".\Data\Frames_",currentTime_str,".mat");

% 发送指令，处理callback
SendCanSignal(handles);


%% 遥测函数：发送连续指令
% --- Executes on button press in togglebutton_SendCanSignalContinuously.
function togglebutton_SendCanSignalContinuously_Callback(hObject, eventdata, handles)
% hObject    handle to togglebutton_SendCanSignalContinuously (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of togglebutton_SendCanSignalContinuously

% 全局变量定义
global DEVICETYPE;
global DEVICEINDEX;
global CANINDEX;
global val;
global sendcnt;
global recvcnt;
global can_signal;
global can_signal_str;
global can_signal_stdid;
global can_signal_rxdata;
global FRAME;
global SENDNUMS;
global SunCoorX;
global SunCoorY;
global SunAngleX;
global SunAngleY;
global StoreFileName;

sendcnt=0;
recvcnt=0;

% 读取一遍选择的命令
select_can_signal(handles);

% 设置 CAN 指令
can_signal = init_CAN();
can_signal('ID') = bin2dec(strcat('000',can_signal_stdid,'000'));
can_signal = set_CAN_Data(can_signal, can_signal_rxdata);
FRAME = gen_CAN_Frame(can_signal);
SENDNUMS = can_signal('SendNums');

% 判断按键是否按下
val = get(hObject,'value');
if val      % 若值为1 按键启动，为绿色，继续运行程序；若值为0，按键关闭，直接退出；
    set(handles.togglebutton_SendCanSignalContinuously,'BackgroundColor','g');
else
    set(handles.togglebutton_SendCanSignalContinuously,'BackgroundColor','r');
    return;
end

% 创建存储文件名称
if val
    currentTime = datetime('now'); 
    currentTime_str = datestr(currentTime,'yyyy_mm_dd_HH_MM_SS');
    StoreFileName = strcat(".\Data\FrameCell_",currentTime_str,".mat");
end

% 持续发送
while val % 判断在按键按下的时候，发送 CAN 指令解析结果
    SendCanSignal(handles);
%     pause(0.01);
end


%% Can函数：发送 CAN 指令，根据不同情况进行处理
function SendCanSignal(handles)
% 全局变量定义
global DEVICETYPE;
global DEVICEINDEX;
global CANINDEX;
global val;
global sendcnt;
global recvcnt;
global can_signal;
global can_signal_str;
global can_signal_stdid;
global can_signal_rxdata;
global FRAME;
global SENDNUMS;
global SunCoorX;
global SunCoorY;
global SunAngleX;
global SunAngleY;
global RevanswerData;
global saveline;
global FramesCell;
global rtc_time;
global StoreFileName;

sendcnt=0;
recvcnt=0;

RevanswerData = char(zeros(8,2));
RevanswerData(1,1) = '3';
RevanswerData(1,2) = 'A';
RevanswerData(2,1) = 'F';
RevanswerData(2,2) = 'F';
RevanswerData(3:8,:) = '0';

% 显示指令
% disp(can_signal_str);

% 发送指令，解析数据
switch can_signal_str
    case '默认指令'
        % 接收数据
        [GetLength, Frames] = Can_Communication(FRAME, SENDNUMS, 1);
    case '传图'
        % 接收数据
        [GetLength, Frames] = Can_Communication(FRAME, SENDNUMS, 77);
        
        % 解析数据
        if GetLength == 77
            Rows = find(Frames(:,1)<=1795);
            Data = Frames(Rows, :);
            Data_Process_SinglePicture(handles, Data);
            SunAngleFrames = Frames(1, :);
            FramesSize = size(Frames);
            for i = 1:FramesSize(1)
                if Frames(i,1) == 1796
                   SunAngleFrames = vertcat(SunAngleFrames, Frames(i, :));
                end
            end
            
            global SunCoorX;
            global SunCoorY;
            global SunAngleX;
            global SunAngleY;

            % 解析返回数据
            SunCoorX = typecast(uint8(SunAngleFrames(3,8:11)), 'single');
            SunCoorY = typecast(uint8(SunAngleFrames(3,12:15)), 'single');
            SunAngleX = typecast(uint8(SunAngleFrames(2,8:11)), 'single');
            SunAngleY = typecast(uint8(SunAngleFrames(2,12:15)), 'single');

            % 数据解析正常，设置显示数据
            set(handles.edit_sun_coor_x, 'String', SunCoorX);
            set(handles.edit_sun_coor_y, 'String', SunCoorY);
            set(handles.edit_sun_angle_1, 'String', SunAngleX/pi*180);
            set(handles.edit_sun_angle_2, 'String', SunAngleY/pi*180);
            if SunCoorX > 0 && SunCoorY > 0
                set(handles.text_sun_status, 'String', '有效位：有效');
                set(handles.text_sun_status, 'BackgroundColor', 'g');
            else
                set(handles.text_sun_status, 'String', '有效位：无效');
                set(handles.text_sun_status, 'BackgroundColor', 'r');
            end

            % 存储数据
            saveline = saveline + 1;
            temp = struct();
            temp.frames = Frames;
            temp.SunCoorX = SunCoorX;
            temp.SunCoorY = SunCoorY;
            temp.SunAngleX = SunAngleX/pi*180;
            temp.SunAngleY = SunAngleY/pi*180;
            currentTime = datetime('now'); % 当前时间
            currentTime_str = datestr(currentTime,'yyyy_mm_dd_HH_MM_SS');
            temp.time = currentTime_str;
            FramesCell{end+1} = temp;
            if(saveline == 10)
                save(StoreFileName, 'FramesCell');
                saveline = 0;
            end
        end
    case '实验'
        % 接收数据
        [GetLength, Frames] = Can_Communication(FRAME, SENDNUMS, 48);
        
        disp(Frames);

        % 存储数据
        save(StoreFileName, 'Frames');
    case '遥测'
        % 初始化
        SunCoorX = 0;
        SunCoorY = 0;
        SunAngleX = 0;
        SunAngleY = 0;
        
        % 接收数据
        for i = 1:1
            % 接收数据
            [GetLength, Frames] = Can_Communication(FRAME, SENDNUMS, 6);
            save Frames.mat Frames;
            % 解析数据
            if GetLength == 6
                Data_Process_SunAngle(handles, Frames);
                break;
            end
        end

        % 数据解析正常，设置显示数据
        set(handles.edit_sun_coor_x, 'String', SunCoorX);
        set(handles.edit_sun_coor_y, 'String', SunCoorY);
        set(handles.edit_sun_angle_1, 'String', SunAngleX/pi*180);
        set(handles.edit_sun_angle_2, 'String', SunAngleY/pi*180);
        set(handles.edit_time, 'String', datestr(rtc_time/86400 + datenum(1970,1,1)));
        if SunCoorX > 0 && SunCoorY > 0
            set(handles.text_sun_status, 'String', '有效位：有效');
            set(handles.text_sun_status, 'BackgroundColor', 'g');
        else
            set(handles.text_sun_status, 'String', '有效位：无效');
            set(handles.text_sun_status, 'BackgroundColor', 'r');
        end
    case '修改ID'
        % 接收数据
        for i = 1:1
            [GetLength, Frames] = Can_Communication(FRAME, SENDNUMS, 1);
            hexStr = dec2hex(Frames(:,[8:15]));
            save hexStr.mat hexStr RevanswerData;
            if(isequal(hexStr,RevanswerData))
                set(handles.SendStatus, 'String', '指令发送状态：修改ID发送成功');
                can_signal_stdid = get(handles.edit_Equipment_ID, 'String');
                set(handles.edit_CAN_StdID, 'String', can_signal_stdid);
            end
        end
    case '修改图形固定阈值'
        % 接收数据
        for i = 1:1
            [GetLength, Frames] = Can_Communication(FRAME, SENDNUMS, 1);
            disp(GetLength);
            hexStr = dec2hex(Frames(:,[8:15]));
            if(hexStr == hexStr)
                set(handles.SendStatus, 'String', '指令发送状态：修改图形固定阈值发送成功');
            end
        end
    case '修改太阳能量固定阈值'
        % 接收数据
        for i = 1:1
            [GetLength, Frames] = Can_Communication(FRAME, SENDNUMS, 1);
            disp(GetLength);
            hexStr = dec2hex(Frames(:,[8:15]));
            if(hexStr == hexStr)
                set(handles.SendStatus, 'String', '指令发送状态：修改太阳能量固定阈值发送成功');
            end
        end
    case '修改跟踪阈值'
        % 接收数据
        for i = 1:1
            [GetLength, Frames] = Can_Communication(FRAME, SENDNUMS, 1);
            disp(GetLength);
            hexStr = dec2hex(Frames(:,[8:15]));
            if(hexStr == hexStr)
                set(handles.SendStatus, 'String', '指令发送状态：修改跟踪阈值发送成功');
            end
        end
    case '系统复位'   
            [GetLength, Frames] = Can_Communication(FRAME, SENDNUMS, 1);
            disp(GetLength);
            hexStr = dec2hex(Frames(:,[8:15]));
            if(hexStr == hexStr)
                pause(1);
                set(handles.SendStatus, 'String', '指令发送状态：系统复位发送成功');
            end
    otherwise
        disp('未发送数据');
end


%% 辅助函数：处理芯片返回数据
function Data_Process_SinglePicture(handles, Frames)
% handles: GUI句柄
% Frames: 芯片成像数据
% 处理芯片返回数据
Rows = find(Frames(:,8)>=100);
Data = Frames(Rows, :);
DataSorted = sortrows(Data, 8);
imagex = DataSorted(1:37,9:15);
imagex = reshape(imagex',1,[]);
imagex = imagex(1:255);
imagey = DataSorted(38:74,9:15);
imagey = reshape(imagey',1,[]);
imagey = imagey(1:255);
% 绘图
axes(handles.axes2);
plot_S9132_Source_Image(imagex, imagey);
axes(handles.axes3);
plot_S9132_Process_Image(imagex, imagey);
axes(handles.axes4);
plot_S9132_OutputData(imagex);
title("x轴数据曲线");
axes(handles.axes5);
plot_S9132_OutputData(imagey);
title("y轴数据曲线");


%% 辅助函数：处理芯片返回的太阳角度
function Data_Process_SunAngle(handles, Frames)
% handles: GUI句柄
% Frames: 芯片成像数据
global SunCoorX;
global SunCoorY;
global SunAngleX;
global SunAngleY;
global rtc_time;
global time_cell;

start = 0;
FramesSize = size(Frames);
for i = 1:FramesSize(1)
    if Frames(i,1) == 1793
        start = i;
    end
end
FramesProcess = Frames(start:FramesSize(1),:);
FramesProcess = cat(1, FramesProcess, Frames(1:start-1,:));

% 解析返回数据
save FramesProcess.mat FramesProcess;
SunCoorX = typecast(uint8(FramesProcess(4,8:11)), 'single');
SunCoorY = typecast(uint8(FramesProcess(4,12:15)), 'single');
SunAngleX = typecast(uint8(FramesProcess(3,8:11)), 'single');
SunAngleY = typecast(uint8(FramesProcess(3,12:15)), 'single');
rtc_time = double(typecast(uint8(FramesProcess(5,8:11)), 'int32'));
rtc_time = rtc_time + double(typecast(uint8(FramesProcess(5,12:15)), 'single'))/1000;

currentTime = datetime(now,'ConvertFrom','datenum','Format','yyyy-MM-dd HH:mm:ss.SSS');
time_cell{end+1} = {currentTime, SunCoorX, SunCoorY, SunAngleX, SunAngleY};
if mod(length(time_cell), 100) == 0
    save time_cell.mat time_cell;
    disp(length(time_cell));
end

%% 辅助函数：绘制芯片单维度输出曲线
function plot_S9132_OutputData(input)
% input: 芯片的单维度输出
plot(input);
ylim([0, 256]);
grid on;
xlim([0, 256]);
ylim([0, 256]);
grid on;
xlabel('像素位置');
ylabel('强度值');


%% 辅助函数： 绘制芯片成像
function plot_S9132_Source_Image(imagex, imagey)
% input_x: 芯片x轴输出
% input_y: 芯片y轴输出
sum_x = sum(imagex);
input_x = imagex;
input_x_T = transpose(input_x);
input_y = imagey;
img_process_show = input_x_T * input_y / sum_x;
imshow(img_process_show);
xlabel('x轴像素位置');
ylabel('y轴像素位置');
title("芯片成像原图");

function plot_S9132_Process_Image(imagex, imagey)
% input_x: 芯片x轴输出
% input_y: 芯片y轴输出
sum_x = sum(imagex);
input_x_process = imagex - mean(imagex);
input_x_process(input_x_process<10) = 0;
input_x_process_T = transpose(input_x_process);
input_y_process = imagey - mean(imagey);
input_y_process(input_y_process<10) = 0;
img_process_show = input_x_process_T * input_y_process / sum_x;
imshow(img_process_show);
xlabel('x轴像素位置');
ylabel('y轴像素位置');
title("芯片成像处理图");

function edit_sun_energy_threshold_Callback(hObject, eventdata, handles)
% hObject    handle to edit_sun_energy_threshold (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_sun_energy_threshold as text
%        str2double(get(hObject,'String')) returns contents of edit_sun_energy_threshold as a double

% 取太阳能量固定阈值, 设置指令
sun_threshold = get(handles.edit_sun_energy_threshold, 'String');
% 将数据转变为高位在前
sun_threshold_num = str2num(sun_threshold);
sun_threshold_bin = dec2bin(sun_threshold_num);
sun_threshold_bin = strcat(repmat('0',1,(32-length(sun_threshold_bin))), sun_threshold_bin);
sun_threshold_str = '';
for i=1:4
    temp = dec2hex(bin2dec(sun_threshold_bin((i-1)*8+1:i*8)));
    temp = strcat(repmat('0',1,(2-length(temp))), temp);
    sun_threshold_str = strcat(sun_threshold_str,temp);
end
can_signal_rxdata = strcat('0A1B','02',sun_threshold_str, '00');
set(handles.edit_CAN_rxdata,'String',can_signal_rxdata);
disp(can_signal_rxdata);


% --- Executes during object creation, after setting all properties.
function edit_sun_energy_threshold_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_sun_energy_threshold (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


function edit_can_image_threshold_Callback(hObject, eventdata, handles)
% hObject    handle to edit_can_image_threshold (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_can_image_threshold as text
%        str2double(get(hObject,'String')) returns contents of edit_can_image_threshold as a double

% 取图形固定阈值, 设置指令
image_threshold = get(handles.edit_can_image_threshold, 'String');
image_threshold_num = str2num(image_threshold);
image_threshold_str = pad(dec2hex(image_threshold_num),2,'left','0');
can_signal_rxdata = strcat('0A1B','01',image_threshold_str,'0000','0000');
set(handles.edit_CAN_rxdata,'String',can_signal_rxdata);
disp(can_signal_rxdata);


% --- Executes during object creation, after setting all properties.
function edit_can_image_threshold_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_can_image_threshold (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function edit_can_track_threshold_Callback(hObject, eventdata, handles)
% hObject    handle to edit_can_track_threshold (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_can_track_threshold as text
%        str2double(get(hObject,'String')) returns contents of edit_can_track_threshold as a double

% 取跟踪阈值, 设置指令
track_threshold = get(handles.edit_can_track_threshold, 'String');
% 将数据转变为高位在前
track_threshold_num = str2num(track_threshold);
track_threshold_bin = dec2bin(track_threshold_num);
track_threshold_bin = strcat(repmat('0',1,(16-length(track_threshold_bin))), track_threshold_bin);
track_threshold_str = '';
for i=1:2
    temp = dec2hex(bin2dec(track_threshold_bin((i-1)*8+1:i*8)));
    temp = strcat(repmat('0',1,(2-length(temp))), temp);
    track_threshold_str = strcat(track_threshold_str,temp);
end
can_signal_rxdata = strcat('0A1B','03',track_threshold_str,'00','0000');
set(handles.edit_CAN_rxdata,'String',can_signal_rxdata);
disp(can_signal_rxdata);


% --- Executes during object creation, after setting all properties.
function edit_can_track_threshold_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_can_track_threshold (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function edit_Equipment_ID_Callback(hObject, eventdata, handles)
% hObject    handle to edit_Equipment_ID (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_Equipment_ID as text
%        str2double(get(hObject,'String')) returns contents of edit_Equipment_ID as a double

% 修改ID
gu8_CAN_ID = get(handles.edit_Equipment_ID, 'String');
gu8_CAN_ID_dec = bin2dec(gu8_CAN_ID);
gu8_CAN_ID_str = pad(dec2hex(gu8_CAN_ID_dec),2,'left','0');
can_signal_rxdata = strcat('0A1B','00',gu8_CAN_ID_str,'0000','0000');
set(handles.edit_CAN_rxdata,'String',can_signal_rxdata);
disp(can_signal_rxdata);


% --- Executes during object creation, after setting all properties.
function edit_Equipment_ID_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_Equipment_ID (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function edit_sun_coor_x_Callback(hObject, eventdata, handles)
% hObject    handle to edit_sun_coor_x (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_sun_coor_x as text
%        str2double(get(hObject,'String')) returns contents of edit_sun_coor_x as a double


% --- Executes during object creation, after setting all properties.
function edit_sun_coor_x_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_sun_coor_x (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function edit_sun_coor_y_Callback(hObject, eventdata, handles)
% hObject    handle to edit_sun_coor_y (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_sun_coor_y as text
%        str2double(get(hObject,'String')) returns contents of edit_sun_coor_y as a double


% --- Executes during object creation, after setting all properties.
function edit_sun_coor_y_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_sun_coor_y (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function edit_sun_angle_1_Callback(hObject, eventdata, handles)
% hObject    handle to edit_sun_angle_1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_sun_angle_1 as text
%        str2double(get(hObject,'String')) returns contents of edit_sun_angle_1 as a double


% --- Executes during object creation, after setting all properties.
function edit_sun_angle_1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_sun_angle_1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function edit_sun_angle_2_Callback(hObject, eventdata, handles)
% hObject    handle to edit_sun_angle_2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_sun_angle_2 as text
%        str2double(get(hObject,'String')) returns contents of edit_sun_angle_2 as a double


% --- Executes during object creation, after setting all properties.
function edit_sun_angle_2_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_sun_angle_2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function edit_sun_energy_Callback(hObject, eventdata, handles)
% hObject    handle to edit_sun_energy (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_sun_energy as text
%        str2double(get(hObject,'String')) returns contents of edit_sun_energy as a double


% --- Executes during object creation, after setting all properties.
function edit_sun_energy_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_sun_energy (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function edit_hex_path_Callback(hObject, eventdata, handles)
% hObject    handle to edit_hex_path (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_hex_path as text
%        str2double(get(hObject,'String')) returns contents of edit_hex_path as a double


% --- Executes during object creation, after setting all properties.
function edit_hex_path_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_hex_path (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


% --- Executes on button press in pushbutton_get_hex.
function pushbutton_get_hex_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_get_hex (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global hexPath;
[P,F]= uigetfile('*.hex');
hexPath=[F,P];
set(handles.edit_hex_path,'String',hexPath);


function edit_device_id_Callback(hObject, eventdata, handles)
% hObject    handle to edit_device_id (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_device_id as text
%        str2double(get(hObject,'String')) returns contents of edit_device_id as a double


% --- Executes during object creation, after setting all properties.
function edit_device_id_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_device_id (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function edit_remote_data_Callback(hObject, eventdata, handles)
% hObject    handle to edit_remote_data (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_remote_data as text
%        str2double(get(hObject,'String')) returns contents of edit_remote_data as a double


% --- Executes during object creation, after setting all properties.
function edit_remote_data_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_remote_data (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


% --- Executes on button press in pushbutton_remote_control.
function pushbutton_remote_control_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_remote_control (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
data=get(handles.edit_remote_data,'string');
id = get(handles.edit_device_id,'string');
reframes =1;
retimeout = 200;
val1 = hexstr2num(data);
Command_Deal2(val1,id,reframes,retimeout);


% --- Executes on button press in pushbutton_enter_boot.
function pushbutton_enter_boot_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_enter_boot (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
data='0A 1B 00 01 00 00 00 00'; % 特定遥控指令，表示控制下位机进入boot状态
id = get(handles.edit_device_id,'string');
reframes =1;
retimeout = 200;
val1 = hexstr2num(data);
Command_Deal2(val1,id,reframes,retimeout);


% --- Executes on button press in pushbutton_exit_boot.
function pushbutton_exit_boot_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_exit_boot (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
data='0A 1B 00 00 00 00 00 00'; % 特定遥控指令，表示控制下位机进入boot状态
id = get(handles.edit_device_id,'string');
reframes =1;
retimeout = 200;
val1 = hexstr2num(data);
Command_Deal2(val1,id,reframes,retimeout);

% --- Executes on button press in pushbutton_boot_load.
function pushbutton_boot_load_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_boot_load (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

global hexPath;
% d ='ARM_201.hex';
d=hexPath;
B=textread(d,'%s');
if contains(d,'hex')
    C=char(B);
    C(:,1:7)=[];
    Not_data=find(C(:,2)~='0');
    C(Not_data,:)=[];
    C(:,1:2)=[];
    [m,n]=size(C);
    for i=1:m
        for j=1:n
            if C(i,j)== ' '
                C(i,j-2:j-1)='  '; 
                break;
            end
        end
    end
    C(:,33:34)=[];
    [m,n]=size(C);
    D=zeros(65536,1);
    k=1;
    for i=1:m
        for j=1:2:n-1  
            if j<32 && C(i,j)~=' '
                D(k,1)=hex2dec(C(i,j:j+1));
                k=k+1;           
            else
                break;
            end
        end
    end
    ProDataBuf=D';
end
len=k-1;
crc=0;
for j=1:1:len
%     crc ^= rev_data(i,1);
    crc=bitxor(crc,ProDataBuf(1,j));
    for k=1:1:8
        if(bitget(crc,1:1))
            crc = bitxor(floor(crc/2),140);
        else
            crc=(crc/2);
        end
    end
end
armcrc=crc;
sendnum=ceil(len/4096);
[~,len]=size(ProDataBuf);
%首帧
m = ceil(len/4096);
data=zeros(1,m*4096);
data(1:len)=ProDataBuf;
realdata=reshape(data,4096,[])';
id=get(handles.edit_device_id,'string');
for i=1:sendnum
    offset=4096*(i-1);
    data ='0B 3B FF 00 00 00 00 00';
    
    reframes = 514;
    retimeout = 3000;
    val1 = hexstr2num(data);    %16进制-10进制
    val1(4)=mod(floor(offset/65536),256);
    val1(5)=mod(floor(offset/256),256);
    val1(6)=mod(offset,256);
    val1(7)=armcrc;
    findata = CanSendDataFill(val1,4096,realdata(i,1:end));
    Command_Deal(findata,id,reframes,retimeout);
    pause(10);
end
disp('上注完成');


% --- Executes on button press in pushbutton_check.
function pushbutton_check_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_check (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global hexPath;
global redata;
% d ='ARM_201.hex';
d=hexPath;
B=textread(d,'%s');
if contains(d,'hex')
    C=char(B);
    C(:,1:7)=[];
    Not_data=find(C(:,2)~='0');
    C(Not_data,:)=[];
    C(:,1:2)=[];
    [m,n]=size(C);
    for i=1:m
        for j=1:n
            if C(i,j)== ' '
                C(i,j-2:j-1)='  '; 
                break;
            end
        end
    end
    C(:,33:34)=[];
    [m,n]=size(C);
    D=zeros(65536,1);
    k=1;
    for i=1:m
        for j=1:2:n-1  
            if j<32 && C(i,j)~=' '
                D(k,1)=hex2dec(C(i,j:j+1));
                k=k+1;           
            else
                break;
            end
        end
    end
    ProDataBuf=D';
end
len=k-1;
crc=0;
for j=1:1:len
%     crc ^= rev_data(i,1);
    crc=bitxor(crc,ProDataBuf(1,j));
    for k=1:1:8
        if(bitget(crc,1:1))
            crc = bitxor(floor(crc/2),140);
        else
            crc=(crc/2);
        end
    end
end
armcrc=crc;
data='0A 1B 01 00 00 00 00 00';
id = get(handles.edit_device_id,'string');
reframes =1;
retimeout = 200;
val1 = hexstr2num(data);
val1(4)=armcrc;
val1(5)=mod(floor(len/65536),256);
val1(6)=mod(floor(len/256),256);
val1(7)=mod(len,256);
Command_Deal2(val1,id,reframes,retimeout);

redata=0;
rec_ok_flag=CanRecTimeOutFast(1,10);
% Recive_id=ReciveIdGet(curpipe,Deal_Num);

if rec_ok_flag == 1
    Common_Receive();       
    if redata(1)==10 && redata(2)==59 && redata(3)==255 && redata(4)==85 ...
            && redata(5)==170 && redata(6)==0 && redata(7)==0 && redata(8)==0
        disp('校验成功');
    else
        disp('校验失败');
    end
end

%% --- 辅助函数 ---
% --- 与下位机进行通信的辅助函数1
function Command_Deal(data,id,reframes,retimeout)
%发送数据
send_data=data;
[~,slen] = size(send_data);
send_step = floor(slen/8);
val1 = mod(slen,8);
if val1~=0
    send_step = send_step+1;
end
for i=1:send_step
    if i==1
        IDbit=[0 1 1 0 0 0 0 0 0 0 1];
    elseif  i==send_step
        IDbit=[0 1 1 0 0 0 0 0 0 1 1];
    else 
        IDbit=[0 1 1 0 0 0 0 0 0 1 0];
    end
    for m=1:5
        IDbit(m+3)=bin2dec(id(m));
    end
    IDdec=mat2str(IDbit);
    ID=bin2dec(IDdec(2:end-1));
    if slen>=8
        send_byte_num = 8;
        slen = slen-8;
    else
        send_byte_num = slen;
    end
    SdataS = 1+(i-1)*8;
    SdataE = (i-1)*8 + send_byte_num;
    sData = send_data(SdataS:SdataE);
    Success = CanSendFrame(ID,sData,send_byte_num);
    disp(strcat('CanSendFrame 运行结果：', num2str(Success)));

end

% --- 与下位机进行通信的辅助函数2。
function Command_Deal2(data,id,reframes,retimeout)
% 发送数据
send_data=data;
[~,slen] = size(send_data);
send_step = floor(slen/8);
val1 = mod(slen,8);
if val1~=0
    send_step = send_step+1;
end
for i=1:send_step
        IDbit=[0 1 1 0 0 0 0 0 0 0 0];
    for m=1:5
        IDbit(m+3)=bin2dec(id(m));
    end
    IDdec=mat2str(IDbit);
    ID=bin2dec(IDdec(2:end-1));
    if slen>=8
        send_byte_num = 8;
        slen = slen-8;
    else
        send_byte_num = slen;
    end
    SdataS = 1+(i-1)*8;
    SdataE = (i-1)*8 + send_byte_num;
    sData = send_data(SdataS:SdataE);
    Success = CanSendFrame(ID,sData,send_byte_num);
    disp(strcat('CanSendFrame 运行结果：', num2str(Success)));
end

% --- can发送数据函数。
function Success=CanSendFrame(id,send_data,dlc)
Device_type = 4;
Device_index = 0;
Can_index = 0; 
FrameFormat = 0;
FrameType = 0;
TimeStamp=0;
TimeFlag=0;
SendType=1;%0-自动重发1-不重发
SendNums=1;
Data = send_data(1:dlc);
Reserved=[0 0 0];
Frames=[id TimeStamp TimeFlag SendType FrameType FrameFormat dlc Data Reserved];
try
    Success = VCI_Transmit(Device_type,Device_index,Can_index, Frames,SendNums); %发送成功的帧数
catch
    Success = 0; 
end

% --- 确认设备 ---
function Common_Receive()
global  redata;
datanum =0;
Res = 1;
redata =[];
ids=[];
Device_type = 4;
Device_index = 0;
Can_index = 0; 
try
    [GetLength,Frames]=VCI_Receive(Device_type,Device_index,Can_index,1,20);
catch
    GetLength = 0;
end

if GetLength==0 || GetLength==hex2dec('FFFFFFFF')
%     Res = 0;
    return;
end
% OutStr={};
% frames = GetLength;
if GetLength
    for i=1:GetLength  
        CurFrame = Frames(i,:);
        ID=CurFrame(1);
        len = CurFrame(7);
        CurFrameData = CurFrame(8:(7+len));
%         RemoteFlag = CurFrame(5);
%         ExternFlag = CurFrame(6);     
%         
%         ids = [ids ID];
        redata = CurFrameData;
    end
end

% --- can返回数据
function rec_ok_flag = CanRecTimeOutFast(frames,RecTime)
Device_type = 4;
Device_index = 0;
Can_index = 0; 

m=0;
loop =0;
if RecTime==0
    CurRecTime=1;
else
    CurRecTime = RecTime;
end

while m<frames 
    try
        m = VCI_GetReceiveNum(Device_type,Device_index,Can_index);
    catch
    end
    %1ms
    DelayMsNoblock(10);

    loop = loop+1;
    if loop==CurRecTime
        rec_ok_flag =0;
        return;
    end
end
rec_ok_flag =1;

% --- 延时 --- 
function DelayMsNoblock(time)
    
% delaytimes=tic;
% while(toc(delaytimes)<(time/1000))
% end

loop  = 100*time;
for i=1:5000
    for j =1:loop
    end
end

% --- 转换hex字符数据 ---
function re = hexstr2num(instr)
data1=[];
[m,~]=size(instr);
for i=1:m
    substr = instr(i,:);
    tran1=textscan(substr,'%02s');
    tran2=tran1{1};
    Fdata = hex2dec(tran2);
    send_data = Fdata';
    data1 = [data1 send_data];
end
re = data1;
    
% --- CanSendDataFill ---
function data = CanSendDataFill(sbuf,slen,realdata)
send_step = floor(slen/8);
val1 = mod(slen,8);
if val1~=0 
    send_step = send_step+1;
end
[~,DataLen]=size(realdata);
if DataLen==0
else
    for i =1:send_step
           bss = (1+i*8);
           bse = (8+i*8);
           ss = ((i-1)*8+1);
           se = (i*8);
           sbuf(bss:bse) = realdata(ss:se);
           DataLen = DataLen-8;
    end
end
sbuf(4096+9:4096+15)=0;
crc=0;
for j=1:1:4096
    crc=bitxor(crc,realdata(1,j));
    for k=1:1:8
        if(bitget(crc,1:1))
            crc = bitxor(floor(crc/2),140);
        else
            crc=(crc/2);
        end
    end
end
sbuf(4112)=crc;
data = sbuf;



function edit_CAN_StdID_Callback(hObject, eventdata, handles)
% hObject    handle to edit_CAN_StdID (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_CAN_StdID as text
%        str2double(get(hObject,'String')) returns contents of edit_CAN_StdID as a double


% --- Executes during object creation, after setting all properties.
function edit_CAN_StdID_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_CAN_StdID (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function edit_CAN_rxdata_Callback(hObject, eventdata, handles)
% hObject    handle to edit_CAN_rxdata (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_CAN_rxdata as text
%        str2double(get(hObject,'String')) returns contents of edit_CAN_rxdata as a double


% --- Executes during object creation, after setting all properties.
function edit_CAN_rxdata_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_CAN_rxdata (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


% --- Executes on button press in pushbutton_connect_load_can.
function pushbutton_connect_load_can_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_connect_load_can (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

global savecnt;
savecnt=1;
rec =open_load_can();
if rec==0
    set(handles.text_LED1, 'ForegroundColor', 'green');
end


% --- Executes on button press in pushbutton_start_load_can.
function pushbutton_start_load_can_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_start_load_can (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

res = start_load_can();
if res==0
    set(handles.text_LED2, 'ForegroundColor', 'green');
end


% --- Executes on button press in pushbutton_close_load_can.
function pushbutton_close_load_can_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_close_load_can (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

res = close_load_can();
if res==0
    set(handles.text_LED1, 'ForegroundColor', 'red');
    set(handles.text_LED2, 'ForegroundColor', 'red');
end

% --- 打开上注程序的 can 接口
function Res = open_load_can()
global CanOpened;
Res=0;
%ARGIN---LINK ARGTAB

Device_type = 4;
Device_index = 0;
Can_index = 0; 

if CanOpened ==0
    VRec = VCI_OpenDevice(Device_type,Device_index,Can_index);
else
    VRec=1;
end
if VRec
    Timing0 = 0;  
    Timing1 = 28; 
    Filter = 1;
    Mode = 0;
    Code = 0;
    Mask = 4294967295;
    Reserved = 0;

    InitConfig=[Code Mask Reserved Filter Timing0 Timing1 Mode];
    if CanOpened ==0
        if  VCI_InitCAN(Device_type,Device_index,Can_index,InitConfig)~=1                
%             msgbox('Init CAN失败！');
            Res=1;
        else
            CanOpened=1;
            Res=0;
        end
    end
else
%     msgbox('OPen CAN失败！');
    Res=2;
end

% --- 启动上注程序的 can 接口
function Res = start_load_can()
Device_type = 4;
Device_index = 0;
Can_index = 0; 

Res = 0;
if VCI_StartCAN(Device_type,Device_index,Can_index)~= 1
    disp('启动CAN失败！');
    Res = 1;
end

% --- 关闭上注程序的 can 接口
function Res = close_load_can()
global CanOpened;
Res = 0;

Device_type = 4;
Device_index = 0;

if VCI_CloseDevice(Device_type,Device_index)~= 1
    disp('关闭CAN失败！');
    Res = 1;
else
    CanOpened=0;
end

function edit_time_Callback(hObject, eventdata, handles)
% hObject    handle to edit_time (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_time as text
%        str2double(get(hObject,'String')) returns contents of edit_time as a double


% --- Executes during object creation, after setting all properties.
function edit_time_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_time (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function [ date ] = ConvertDate( x )
%将unix时间戳转换为标准时间
% date = datestr(1426406400/86400 + datenum(1970,1,1));
date = datestr((x-3600*24+8*3600)/86400 + 70*365+19+datenum(1900,1,0));
